#pragma once
#include <iostream>
#include <list>

/**@note suitable for situations where adding and deleting is frequent.*/
template<typename T>
class CList : public std::list<T> {
public:
    CList() = default;

    CList(std::initializer_list<T> init) : std::list<T>(init) {}

    bool removeOne(const T& value) {
        auto initialSize = this->size();
        this->remove(value);
        bool success = initialSize - this->size() == 1;
        return success;
    }

    void removeFirst() {// efficiency: O(1)
        if (this->empty())
            return;
        this->pop_front();
    }

    void removeLast() {// efficiency: O(1)
        if (this->empty())
            return;
        this->pop_back();
    }

    CList& operator<<(const T& value) {
        this->push_back(value);
        return *this;
    }

    friend std::ostream& operator<<(std::ostream &os, const CList &list) {
        os << "Size: " << list.size() << ", Elements: [";
        for (int i = 0; i < list.size(); ++i) {
            os << list[i];
            if (i != list.size() - 1) os << ", ";
        }
        os << "]";
        return os;
    }
};